using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.IO;
using System.Reflection;
using System.Security;

namespace AssemblyVerifier.Tests
{
	[TestClass, SecurityCritical]
	public sealed class VerificationTests
	{
		[TestMethod]
		[DeploymentItem("GoodAssembly.il")]
		public void VerifyAssemblyViaFileInfo()
		{
			AssemblyCreator.Create("GoodAssembly.il", "/dll");
			AssemblyVerification.Verify(new FileInfo("GoodAssembly.dll"));
		}
	
		[TestMethod]
		[DeploymentItem("BadAssembly.il")]
		[ExpectedException(typeof(VerificationException))]
		public void VerifyAssemblyWithVerificationErrorsViaFileInfo()
		{
			AssemblyCreator.Create("BadAssembly.il", "/dll");
			
			try
			{
				AssemblyVerification.Verify(new FileInfo("BadAssembly.dll"));
			}
			catch(VerificationException ex)
			{
				Assert.AreEqual(1, ex.Errors.Count, "The count is incorrect.");

				foreach(var error in ex.Errors)
				{
					this.TestContext.WriteLine("Type: {0}, location: {1}, description: {2}",
						 error.GetType().Name, error.Location, error.Description);
				}

				throw;
			}
		}

		[TestMethod]
		[ExpectedException(typeof(ArgumentNullException))]
		public void VerifyAssemblyViaNullFileInfo()
		{
			AssemblyVerification.Verify(null as FileInfo);
		}

		[TestMethod]
		[ExpectedException(typeof(FileNotFoundException))]
		public void VerifyAssemblyViaFileDoesNotExist()
		{
			AssemblyVerification.Verify(
				new FileInfo(Guid.NewGuid().ToString() + ".dll"));
		}


		[TestMethod]
		[DeploymentItem("GoodAssembly.il")]
		public void VerifyAssemblyViaAssemblyReference()
		{
			AssemblyCreator.Create("GoodAssembly.il", "/dll");

			var name = new AssemblyName(
				"GoodAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
			AssemblyVerification.Verify(Assembly.Load(name));
		}

		[TestMethod]
		[DeploymentItem("BadAssembly.il")]
		[ExpectedException(typeof(VerificationException))]
		public void VerifyAssemblyWithVerificationErrorsViaAssemblyReference()
		{
			AssemblyCreator.Create("BadAssembly.il", "/dll");

			try
			{
				var name = new AssemblyName(
					"BadAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
				AssemblyVerification.Verify(Assembly.Load(name));
			}
			catch(VerificationException ex)
			{
				Assert.AreEqual(1, ex.Errors.Count, "The count is incorrect.");

				foreach(var error in ex.Errors)
				{
					this.TestContext.WriteLine("Type: {0}, location: {1}, description: {2}",
						 error.GetType().Name, error.Location, error.Description);
				}

				throw;
			}
		}

		[TestMethod]
		[ExpectedException(typeof(ArgumentNullException))]
		public void VerifyAssemblyViaNullAssemblyReference()
		{
			AssemblyVerification.Verify(null as Assembly);
		}

		public TestContext TestContext { get; set; }
	}
}
